package top.jidanmian.iot.server.mqtt;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttMessageListener;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.StandardCharsets;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

@Configuration
@Slf4j
public class MqttConfiguration {
    private MqttClient mqttClient;
    private final MqttConfigBuilder config;
    public MqttConfiguration(MqttConfigBuilder config) {
        this.config = config;
    }

    @PostConstruct
    private void init() {
        createMqttClient();
        connect();
    }

    private void connect() {
        if (mqttClient.isConnected()) return;

        try {
            mqttClient.connect(config.getOptions());
            log.debug("连接MQTT服务器：成功");
        } catch (MqttException e) {
            log.error("连接MQTT服务器：失败 - {}", e.toString());
        }
    }

    private void createMqttClient() {
        try {
            mqttClient = new MqttClient(config.getHost(), MqttClient.generateClientId(), new MemoryPersistence());
            mqttClient.setCallback(new MqttCallback() {

                @Override
                public void connectionLost(Throwable cause) {
                    log.warn("MQTT服务器连接：断开 - {}", cause.toString());
                }

                @Override
                public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                    String message = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8);
                    log.info("收到MQTT消息 - topic：{} - message: {}", topic, message);
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    try {

                        log.debug("MQTT消息发送完成 - {}", new String(token.getMessage().getPayload(), StandardCharsets.UTF_8));
                    } catch (MqttException e) {
                        log.error("MQTT消息发送完成回调函数出错 - {}", e.toString());
                    }
                }
                
            });
        } catch (MqttException e) {
            log.error("创建MQTT Client失败 - {}", e.toString());
        }
    }

    public boolean publish(String topic, String message) {
        return publish(topic, 0, message);
    }

    public boolean publish(String topic, int qos, String message) {
        log.debug("发布MQTT消息 - topic: {}, messagte: {}", topic, message);

        if (mqttClient.isConnected()) {

            MqttMessage mqttMessage = new MqttMessage();
            mqttMessage.setPayload(message.getBytes(StandardCharsets.UTF_8));
            mqttMessage.setQos(qos);
            try {
                mqttClient.publish(topic, mqttMessage);
                return true;
            } catch (MqttException e) {
                log.error("MQTT消息发送失败 - {}", e.toString());
            }
        }
        return false;
    }

    public boolean subscribe(String topic) {
        return subscribe(topic, 0);
    }

    public boolean subscribe(String topic, int qos) {
        log.debug("订阅MQTT主题 - topic: {}", topic);

        if (mqttClient.isConnected()) {
            try {
                mqttClient.subscribe(topic, qos, new IMqttMessageListener() {
                    @Override
                    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
                        String message = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8);
                        log.info("收到MQTT订阅信息 - topic: {}, message: {}", topic, message);
                    }
                });
            } catch (MqttException e) {
                log.error("订阅MQTT主题：失败 - {}", e.toString());
            }
        }

        return false;
    }

    public void unsubscribe(String topic) {
        log.debug("取消MQTT订阅 - topic: {}", topic);
        if (mqttClient.isConnected()) {
            try {
                mqttClient.unsubscribe(topic);
            } catch (MqttException e) {
                log.error("取消MQTT订阅失败 - {}", e.toString());
            }
        }
    }
}
